package it.crudity.web.json;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;

/***
 * Aspect that intercepts controllers for json filtering
 */
@Aspect
public class JsonFilterAspect {

	@Around("within(@org.springframework.stereotype.Controller *) && execution(@JsonFilter public * *(..))")
	public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
		final Object realResult = pjp.proceed();
		MethodSignature msig = (MethodSignature) pjp.getSignature();
		/* Grab the annotation. */
		JsonFilter annotation = msig.getMethod().getAnnotation(JsonFilter.class);
		final Class<?> mixin = annotation.mixin();

		Object proxy = Enhancer.create(realResult.getClass(), new Class[] { JsonFilteredBean.class },
				new MethodInterceptor() {
					@Override
					public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy)
							throws Throwable {
						if (method.getDeclaringClass().equals(JsonFilteredBean.class))
							return mixin;
						else
							return proxy.invoke(realResult, args);
					}
				});

		return proxy;
	}
}
